import { Logger } from './Logger'

// 文件名解析器（责任链模式）
export class FileNameParser {
  constructor() {
    this.successor = null
    this.logger = Logger.getInstance()
  }
  
  setSuccessor(successor) {
    this.successor = successor
    return successor
  }
  
  parse(fileName) {
    // 由子类实现具体解析逻辑
    throw new Error('抽象方法，需要子类实现')
  }
  
  // 如果当前解析器无法处理，传递给下一个解析器
  passToSuccessor(fileName) {
    if (this.successor) {
      return this.successor.parse(fileName)
    }
    // 没有后继解析器，返回null
    this.logger.warning(`无法解析文件名: ${fileName}`)
    return null
  }
}

// 标准格式解析器 - 解析"实验X_学号_姓名.doc"格式
export class StandardFormatParser extends FileNameParser {
  parse(fileName) {
    // 匹配格式: 实验X_学号_姓名.doc 或 实验X_学号_姓名.docx
    const regex = /^实验(\d+)_(\d+)_(.+)\.(doc|docx)$/
    const match = fileName.match(regex)
    
    if (match) {
      return {
        experimentNum: parseInt(match[1]),
        studentId: match[2],
        studentName: match[3],
        fileType: match[4],
        fileName: fileName
      }
    }
    
    return this.passToSuccessor(fileName)
  }
}

// 宽松格式解析器 - 解析包含学号和实验编号的文件名
export class LooseFormatParser extends FileNameParser {
  parse(fileName) {
    // 尝试提取学号 - 假设学号为连续的5-12位数字
    const studentIdMatch = fileName.match(/(\d{5,12})/)
    
    // 尝试提取实验编号 - 寻找 "实验X" 或 "expX" 或 "labX" 等模式
    const experimentMatch = fileName.match(/实验(\d+)/i) || 
                             fileName.match(/exp(\d+)/i) ||
                             fileName.match(/lab(\d+)/i)
    
    if (studentIdMatch && experimentMatch) {
      return {
        experimentNum: parseInt(experimentMatch[1]),
        studentId: studentIdMatch[1],
        studentName: null, // 无法可靠提取姓名
        fileType: fileName.split('.').pop(),
        fileName: fileName
      }
    }
    
    return this.passToSuccessor(fileName)
  }
}

// 最后兜底解析器 - 尽可能提取信息
export class FallbackParser extends FileNameParser {
  parse(fileName) {
    const fileType = fileName.split('.').pop()
    
    // 尝试提取任何可能的数字作为实验编号和学号
    const numbers = fileName.match(/\d+/g) || []
    
    // 如果找到至少两个数字，假设第一个是实验编号，第二个是学号
    if (numbers.length >= 2) {
      return {
        experimentNum: parseInt(numbers[0]),
        studentId: numbers[1],
        studentName: null,
        fileType: fileType,
        fileName: fileName
      }
    } else if (numbers.length === 1) {
      // 只找到一个数字，尝试猜测它是学号还是实验编号
      const num = numbers[0]
      if (num.length >= 5) { // 长数字更可能是学号
        return {
          experimentNum: null,
          studentId: num,
          studentName: null,
          fileType: fileType,
          fileName: fileName
        }
      } else { // 短数字更可能是实验编号
        return {
          experimentNum: parseInt(num),
          studentId: null,
          studentName: null,
          fileType: fileType,
          fileName: fileName
        }
      }
    }
    
    // 最后兜底，返回尽可能多的信息
    return {
      experimentNum: null,
      studentId: null,
      studentName: null,
      fileType: fileType,
      fileName: fileName,
      isParsed: false
    }
  }
}

// 文件分析器 - 分析实验报告文件
export class FileAnalyzer {
  constructor() {
    this.logger = Logger.getInstance()
    
    // 设置责任链
    this.parser = new StandardFormatParser()
    const looseParser = new LooseFormatParser()
    const fallbackParser = new FallbackParser()
    
    this.parser.setSuccessor(looseParser)
    looseParser.setSuccessor(fallbackParser)
  }
  
  // 分析单个文件
  analyzeFile(fileName) {
    return this.parser.parse(fileName)
  }
  
  // 批量分析文件
  analyzeFiles(fileNames) {
    const results = []
    const errors = []
    
    fileNames.forEach(fileName => {
      try {
        const result = this.analyzeFile(fileName)
        results.push(result)
        
        // 记录不完整的解析结果
        if (!result.studentId || !result.experimentNum) {
          this.logger.warning(`文件解析不完整: ${fileName}`, result)
        }
      } catch (error) {
        this.logger.error(`文件解析错误: ${fileName}`, error)
        errors.push({ fileName, error: error.message })
      }
    })
    
    return { results, errors }
  }
  
  // 验证解析结果与学生名单
  validateWithStudentList(parseResults, students) {
    const validResults = []
    const invalidResults = []
    
    parseResults.forEach(result => {
      if (!result.studentId) {
        invalidResults.push({
          ...result,
          error: '无法提取学号'
        })
        return
      }
      
      // 查找对应的学生
      const student = students.find(s => s.studentId === result.studentId)
      
      if (!student) {
        invalidResults.push({
          ...result,
          error: '学号不在学生名单中'
        })
      } else {
        // 如果解析出了学生姓名，检查是否匹配
        if (result.studentName && result.studentName !== student.name) {
          this.logger.warning(`文件名中的姓名与学生名单不匹配: ${result.fileName}`, {
            fileNameStudent: result.studentName,
            listStudent: student.name
          })
        }
        
        validResults.push({
          ...result,
          student: student
        })
      }
    })
    
    return { validResults, invalidResults }
  }
  
  // 统计实验提交情况
  analyzeSubmissions(validResults, students, experimentCount) {
    // 按学生统计缺交情况
    const studentStats = students.map(student => {
      const submittedExperiments = validResults
        .filter(r => r.student.id === student.id)
        .map(r => r.experimentNum)
      
      const missingExperiments = []
      for (let i = 1; i <= experimentCount; i++) {
        if (!submittedExperiments.includes(i)) {
          missingExperiments.push(`实验${i}`)
        }
      }
      
      return {
        ...student,
        missingCount: missingExperiments.length,
        missingExperiments: missingExperiments,
        submittedCount: submittedExperiments.length
      }
    })
    
    // 按实验统计缺交情况
    const experimentStats = []
    for (let i = 1; i <= experimentCount; i++) {
      const experimentNum = i
      const submittedStudents = validResults
        .filter(r => r.experimentNum === experimentNum)
        .map(r => r.student)
      
      const submittedStudentIds = submittedStudents.map(s => s.id)
      
      const missingStudents = students.filter(student => 
        !submittedStudentIds.includes(student.id)
      )
      
      experimentStats.push({
        experimentName: `实验${experimentNum}`,
        experimentId: experimentNum,
        submittedCount: submittedStudents.length,
        missingCount: missingStudents.length,
        totalCount: students.length,
        submitRate: submittedStudents.length / students.length,
        missingStudents: missingStudents
      })
    }
    
    return { studentStats, experimentStats }
  }
} 